package com.xiyi.shouxin.service;

import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.xiyi.shouxin.dao.admin.AdminRepository;
import com.xiyi.shouxin.dao.admin.MenuRepository;
import com.xiyi.shouxin.dao.admin.RoleMenuRefRepository;
import com.xiyi.shouxin.dao.admin.RoleRepository;
import com.xiyi.shouxin.entity.admin.Admin;
import com.xiyi.shouxin.entity.admin.Menu;
import com.xiyi.shouxin.entity.admin.Role;
import com.xiyi.shouxin.entity.admin.RoleMenuRef;
import com.xiyi.shouxin.entity.admin.mapper.AdminMapper;
import com.xiyi.shouxin.entity.admin.mapper.MenuMapper;
import com.xiyi.shouxin.entity.admin.mapper.RoleMapper;
import com.xiyi.shouxin.exception.CommonException;
import com.xiyi.shouxin.exception.ErrorCode;
import com.xiyi.shouxin.utils.MD5Util;
import com.xiyi.shouxin.view.pojo.AdminView;
import com.xiyi.shouxin.view.pojo.ItemPage;
import com.xiyi.shouxin.view.pojo.MenuView;
import com.xiyi.shouxin.view.pojo.RoleView;

@Service
public class AdminService {
    @Autowired
    private AdminRepository adminRepository;
    @Autowired
    private RoleRepository roleRepository;
    @Autowired
    private RoleMenuRefRepository roleMenuRefRepository;
    @Autowired
    private MenuRepository menuRepository;

    /*
     * 管理员列表
     */
    public ItemPage<AdminView> findAdminList(Admin operator, String keyword, int page, int size) throws Exception {
        List<AdminView> list = new ArrayList<>();
        List<Admin> result = new ArrayList<>();
        int total = 0;
        Sort sort = Sort.by(Direction.DESC, "id");
        if (operator != null && operator.getRoleId() != null
                && operator.getRoleId() != 1L && operator.getId() != null) {
            result = adminRepository.findByMultiConditionsByPage(operator.getId(), keyword, sort, page, size);
            total = adminRepository.countByMultiConditions(operator.getId(), keyword);
        } else {
            result = adminRepository.findByMultiConditionsByPage(null, keyword, sort, page, size);
            total = adminRepository.countByMultiConditions(null, keyword);
        }
        for (Admin admin : result) {
            admin.setPassword(null);
            if (admin.getRoleId() != null) {
                Role role = roleRepository.findById(admin.getRoleId(), new RoleMapper());
                if (role != null) {
                    list.add(new AdminView(admin, new RoleView(role, null)));
                    continue;
                }
            }
            list.add(new AdminView(admin, null));
        }
        return new ItemPage<AdminView>(list, total);
    }

    /*
     * 管理员详情
     */
    public AdminView findAdmin(Admin operator, Long adminId) throws Exception {
        if (operator != null && operator.getRoleId() != null && operator.getRoleId() != 1L) {
            if (!operator.getId().equals(adminId)) {
                throw new CommonException(ErrorCode.NOPERMISSION);
            }
        }
        Admin admin = adminRepository.findById(adminId, new AdminMapper());
        if (admin != null) {
            admin.setPassword(null);
            RoleView roleView = null;
            if (admin.getRoleId() != null) {
                Role role = roleRepository.findById(admin.getRoleId(), new RoleMapper());
                if (role != null) {
                    roleView = new RoleView(role, null);
                }
            }
            return new AdminView(admin, roleView);
        }
        throw new CommonException(ErrorCode.NOTFOUND);
    }

    /*
     * 添加管理员
     */
    public AdminView createAdmin(Admin operator, Admin admin) throws Exception {
        if (admin == null || admin.getRoleId() == null || admin.getPassword() == null || admin.getAccount() == null) {
            throw new CommonException(ErrorCode.INVALIDPARAMTER);
        }
        if (operator != null && operator.getRoleId() != null && operator.getRoleId() != 1L) {
            throw new CommonException(ErrorCode.NOPERMISSION);
        }
        RoleView roleView = null;
        Role role = roleRepository.findById(admin.getRoleId(), new RoleMapper());
        if (role == null) {
            throw new CommonException(ErrorCode.INVALIDPARAMTER);
        }
        roleView = new RoleView(role, null);
        String encryptd;
        try {
            encryptd = MD5Util.MD5Encrypt(admin.getPassword());
        } catch (NoSuchAlgorithmException e) {
            throw new CommonException(ErrorCode.INVALIDPARAMTER);
        }
        admin.setPassword(encryptd);
        admin.setIsDelete("1");
        Long newId = adminRepository.create(admin);
        admin.setId(newId);
        return new AdminView(admin, roleView);
    }

    /*
     * 修改管理员
     */
    public void updateAdmin(Admin operator, Admin admin) throws Exception {
        if (admin == null) {
            throw new CommonException(ErrorCode.INVALIDPARAMTER);
        }
        if (operator != null && operator.getRoleId() != null && operator.getRoleId() != 1L) {
            if (operator.getId() != null && !operator.getId().equals(admin.getId())) {
                throw new CommonException(ErrorCode.NOPERMISSION);
            }
        }
        if (admin.getRoleId() != null) {
            Role role = roleRepository.findById(admin.getRoleId(), new RoleMapper());
            if (role == null) {
                throw new CommonException(ErrorCode.INVALIDPARAMTER);
            }
        }

        if (admin.getPassword() != null) {
            String encryptd;
            try {
                encryptd = MD5Util.MD5Encrypt(admin.getPassword());
            } catch (NoSuchAlgorithmException e) {
                throw new CommonException(ErrorCode.INVALIDPARAMTER);
            }
            admin.setPassword(encryptd);
        }

        adminRepository.update(admin.getId(), admin);
    }

    /*
     * 禁用/启用管理员
     */
    public void disableAdmin(Admin operator, Long adminId, Boolean isDelete) throws Exception {
        if (adminId == null || isDelete == null) {
            throw new CommonException(ErrorCode.INVALIDPARAMTER);
        }
        Admin admin = new Admin();
        if (isDelete) {
            admin.setIsDelete("0");
        } else {
            admin.setIsDelete("1");
        }
        adminRepository.update(adminId, admin);
    }

    /*
     * 删除管理员
     */
    public void delAdmins(Admin operator, List<Long> adminIds) throws CommonException {
        if (adminIds == null || adminIds.isEmpty()) {
            return;
        }
        if (operator != null && operator.getRoleId() != null && operator.getRoleId() != 1L) {
            throw new CommonException(ErrorCode.NOPERMISSION);
        }
        adminRepository.delByIds(adminIds);
    }

    /*
     * 管理员登录
     */
    public AdminView login(String account, String password) throws Exception {
        if (!StringUtils.hasText(account) || !StringUtils.hasText(password)) {
            throw new CommonException(ErrorCode.INVALIDPARAMTER);
        }
        Admin admin = adminRepository.findFirstByAccount(account);
        if (admin == null) {
            throw new CommonException(ErrorCode.INVALIDACCOUNT);
        }

        if (admin.getIsDelete() != null && "0".equals(admin.getIsDelete())) {
            throw new CommonException(ErrorCode.INVALIDACCOUNT);
        }
        String encryptd;
        try {
            encryptd = MD5Util.MD5Encrypt(password);
        } catch (NoSuchAlgorithmException e) {
            throw new CommonException(ErrorCode.WRONGACCOUNT);
        }
        if (encryptd == null || !encryptd.equals(admin.getPassword())) {
            throw new CommonException(ErrorCode.WRONGACCOUNT);
        }
        admin.setPassword(null);

        RoleView roleView = null;
        Role role = roleRepository.findById(admin.getRoleId(), new RoleMapper());
        if (role == null) {
            throw new CommonException(ErrorCode.NOPERMISSION);
        }
        roleView = new RoleView(role, null);
        return new AdminView(admin, roleView);
    }

    /*
     * 生成token
     */
    public String generateTokenForAdmin(Admin admin) {
        return "admin_" + UUID.randomUUID().toString();
    }

    /*
     * 角色列表
     */
    public ItemPage<RoleView> findRoleList(String roleName, int page, int size) throws Exception {
        List<RoleView> list = new ArrayList<>();
        List<Role> result = new ArrayList<>();
        int total = 0;
        Sort sort = Sort.by(Direction.DESC, "id");
        result = roleRepository.findByMultiConditionsByPage(roleName, sort, page, size);
        total = roleRepository.countByMultiConditions(roleName);
        for (Role role : result) {
            list.add(new RoleView(role, null));
        }
        return new ItemPage<>(list, total);
    }

    /*
     * 菜单列表
     */
    public List<MenuView> findAllMenu() throws Exception {
        List<MenuView> menuViews = new ArrayList<>();
        List<Menu> menus = menuRepository.findAll(new MenuMapper());
        for (Menu menu : menus) {
            List<RoleMenuRef> refs = roleMenuRefRepository.findAllByMenuId(menu.getId());
            List<Long> roleIds = new ArrayList<>();
            refs.forEach(ref -> roleIds.add(ref.getRoleId()));
            List<RoleView> roles = new ArrayList<>();
            if (!roleIds.isEmpty()) {
                roleRepository.findAllById(roleIds, new RoleMapper())
                        .forEach(role -> roles.add(new RoleView(role, null)));
            }
            menuViews.add(new MenuView(menu, roles));
        }
        return menuViews;
    }

    /*
     * 添加菜单
     */
    @Transactional(rollbackFor = Exception.class)
    public MenuView createMenu(Admin operator, Menu menu, List<Long> roleIds) throws Exception {
        if (menu == null || menu.getName() == null || menu.getMenuType() == null) {
            throw new CommonException(ErrorCode.INVALIDPARAMTER);
        }
        if (operator != null && operator.getRoleId() != null && operator.getRoleId() != 1L) {
            throw new CommonException(ErrorCode.NOPERMISSION);
        }
        Long newId = menuRepository.create(menu);
        menu.setId(newId);
        List<RoleView> roleViews = new ArrayList<>();
        if (roleIds == null || roleIds.isEmpty()) {
            return new MenuView(menu, roleViews);
        }
        List<Role> roles = roleRepository.findAllById(roleIds, new RoleMapper());
        for (Role role : roles) {
            RoleMenuRef ref = new RoleMenuRef();
            ref.setMenuId(newId);
            ref.setRoleId(role.getId());
            roleMenuRefRepository.create(ref);
            roleViews.add(new RoleView(role, null));
        }
        return new MenuView(menu, roleViews);
    }

    /*
     * 修改菜单
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateMenu(Admin operator, Menu menu, List<Long> roleIds) throws Exception {
        if (menu == null || menu.getId() == null) {
            throw new CommonException(ErrorCode.INVALIDPARAMTER);
        }
        if (operator != null && operator.getRoleId() != null && operator.getRoleId() != 1L) {
            throw new CommonException(ErrorCode.NOPERMISSION);
        }
        menuRepository.update(menu.getId(), menu);
        roleMenuRefRepository.delByMenuId(menu.getId());
        if (roleIds != null && !roleIds.isEmpty()) {
            List<Role> roles = roleRepository.findAllById(roleIds, new RoleMapper());

            for (Role role : roles) {
                RoleMenuRef ref = new RoleMenuRef();
                ref.setMenuId(menu.getId());
                ref.setRoleId(role.getId());
                roleMenuRefRepository.create(ref);
            }
        }
    }

    /*
     * 删除菜单
     */
    @Transactional(rollbackFor = Exception.class)
    public void delMenus(Admin operator, List<Long> menuIds) throws Exception {
        if (operator != null && operator.getRoleId() != null && operator.getRoleId() != 1L) {
            throw new CommonException(ErrorCode.NOPERMISSION);
        }
        if (menuIds == null || menuIds.isEmpty()) {
            throw new CommonException(ErrorCode.INVALIDPARAMTER);
        }
        menuRepository.delByIds(menuIds);
        for (Long menuId : menuIds) {
            roleMenuRefRepository.delByMenuId(menuId);
        }
    }

    /*
     * 管理员菜单列表
     */
    public List<MenuView> findAllMenuByAdmin(Long adminId) throws Exception {
        Admin admin = adminRepository.findById(adminId, new AdminMapper());
        if (admin == null || admin.getRoleId() == null) {
            throw new CommonException(ErrorCode.NOTFOUND);
        }
        List<MenuView> menuViews = new ArrayList<>();
        if (admin.getRoleId() == 1L) {
            menuRepository.findAll(new MenuMapper()).forEach(menu -> menuViews.add(new MenuView(menu, null)));
            return menuViews;
        }
        List<RoleMenuRef> refs = roleMenuRefRepository.findAllByRoleId(admin.getRoleId());
        if (refs == null || refs.isEmpty()) {
            return menuViews;
        }
        List<Long> menuIds = new ArrayList<>();
        for (RoleMenuRef ref : refs) {
            menuIds.add(ref.getMenuId());
        }
        menuRepository.findAllById(menuIds, new MenuMapper()).forEach(menu -> menuViews.add(new MenuView(menu, null)));
        return menuViews;
    }

}
